package frame;

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Rectangle;

import javax.lang.model.element.VariableElement;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JComboBox;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.MutableComboBoxModel;

import org.dom4j.Branch;
import org.dom4j.Comment;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.DocumentType;
import org.dom4j.Element;
import org.dom4j.InvalidXPathException;
import org.dom4j.Node;
import org.dom4j.ProcessingInstruction;
import org.dom4j.QName;
import org.dom4j.Visitor;
import org.dom4j.XPath;
import org.dom4j.io.XMLWriter;
import org.xml.sax.EntityResolver;

import components.AddLinguisticVariableDialog;
import components.AddPointDialog;
import components.AddValueDialog;
import components.GraphPanel;
import components.LinguisticValue;
import components.LinguisticVariable;
import components.Pair;

import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.Color;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.JLabel;

import java.awt.Font;

import javax.swing.UIManager;

public class Main extends JFrame implements MouseListener, ActionListener,
		ItemListener {
	private JMenuItem mntmOpen;
	private JMenuItem mntmSave;
	private JPanel contentPane;
	private ArrayList<LinguisticVariable> variables = new ArrayList<LinguisticVariable>();
	private JPanel graph;
	private int selectedVariableIndex = 0;
	private JComboBox<String> comboBox;
	private JButton addPointButton;
	JButton btnNewButton_1;
	private Document doc = null;
	private File target = null;
	Element rootElt;
	JMenuItem mntmAddLinguisticVarable, mntmDeleteLinguisticVariable;
	JMenuItem mntmAddLinguisticValue, mntmDeleteLinguisticValue;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					Main frame = new Main();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	public Main() {
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 530, 440);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(null);

		// TODO Auto-generated method stub
		graph = new JPanel();
		graph = new GraphPanel(variables);
		graph.setBackground(Color.WHITE);
		graph.setBounds(37, 77, 467, 315);
		contentPane.add(graph);

		comboBox = new JComboBox();
		comboBox.addItemListener(this);
		comboBox.addActionListener(this);
		comboBox.setBounds(10, 33, 88, 21);
		contentPane.add(comboBox);

		addPointButton = new JButton("Add Point");
		addPointButton.addActionListener(this);
		addPointButton.setBounds(288, 32, 93, 23);
		contentPane.add(addPointButton);

		btnNewButton_1 = new JButton("Delete Point");
		btnNewButton_1.addActionListener(this);
		btnNewButton_1.setBounds(399, 32, 105, 23);
		contentPane.add(btnNewButton_1);

		JMenuBar menuBar = new JMenuBar();
		menuBar.setBounds(0, 0, 105, 21);
		contentPane.add(menuBar);

		JMenu mnFile = new JMenu("File");
		menuBar.add(mnFile);

		mntmOpen = new JMenuItem("Open");
		mntmOpen.addActionListener(this);
		mntmOpen.addMouseListener(this);
		mnFile.add(mntmOpen);

		mntmSave = new JMenuItem("Save");
		mntmSave.addActionListener(this);
		mntmSave.addMouseListener(this);
		mnFile.add(mntmSave);

		JMenu mnVariable = new JMenu("Variable");
		mnVariable.setFont(UIManager.getFont("MenuBar.font"));
		menuBar.add(mnVariable);

		mntmAddLinguisticVarable = new JMenuItem("Add Linguistic Varable");
		mntmAddLinguisticVarable.addActionListener(this);
		mnVariable.add(mntmAddLinguisticVarable);

		mntmDeleteLinguisticVariable = new JMenuItem(
				"Delete Linguistic Variable");
		mntmDeleteLinguisticVariable.addActionListener(this);
		mnVariable.add(mntmDeleteLinguisticVariable);

		JMenu mnValue = new JMenu("Value");
		menuBar.add(mnValue);

		mntmAddLinguisticValue = new JMenuItem("Add Linguistic Value");
		mntmAddLinguisticValue.addActionListener(this);
		mnValue.add(mntmAddLinguisticValue);

		mntmDeleteLinguisticValue = new JMenuItem("Delete Linguistic Value");
		mntmDeleteLinguisticValue.addActionListener(this);
		mnValue.add(mntmDeleteLinguisticValue);

		JLabel lblNewLabel = new JLabel("1.0");
		lblNewLabel.setBounds(10, 77, 54, 15);
		contentPane.add(lblNewLabel);

		JLabel lblNewLabel_1 = new JLabel("0");
		lblNewLabel_1.setBounds(10, 363, 54, 15);
		contentPane.add(lblNewLabel_1);

		JLabel label = new JLabel("0.5");
		label.setBounds(10, 223, 54, 15);
		contentPane.add(label);

		JLabel label_1 = new JLabel("0.8");
		label_1.setBounds(10, 139, 54, 15);
		contentPane.add(label_1);

		JLabel label_2 = new JLabel("0.6");
		label_2.setBounds(10, 195, 54, 15);
		contentPane.add(label_2);

		JLabel label_3 = new JLabel("0.7");
		label_3.setBounds(10, 167, 54, 15);
		contentPane.add(label_3);

		JLabel label_4 = new JLabel("0.1");
		label_4.setBounds(10, 335, 54, 15);
		contentPane.add(label_4);

		JLabel label_5 = new JLabel("0.2");
		label_5.setBounds(10, 307, 54, 15);
		contentPane.add(label_5);

		JLabel lblNewLabel_2 = new JLabel("0.3");
		lblNewLabel_2.setBounds(10, 279, 54, 15);
		contentPane.add(lblNewLabel_2);

		JLabel lblNewLabel_3 = new JLabel("0.4");
		lblNewLabel_3.setBounds(10, 251, 54, 15);
		contentPane.add(lblNewLabel_3);

		JLabel label_6 = new JLabel("0.9");
		label_6.setBounds(10, 108, 54, 15);
		contentPane.add(label_6);

		JButton btnNewButton = new JButton("Values & Colors");
		btnNewButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				JDialog dlg = new JDialog();
				dlg.setLayout(new FlowLayout());
				dlg.setSize(300, 100);
				LinguisticVariable var = variables.get(selectedVariableIndex);
				for (LinguisticValue value : var.getLinguisticValues()) {
					JLabel label = new JLabel(value.getName());
					label.setOpaque(false);
					label.setForeground(value.getColor());
					dlg.add(label);
				}
				dlg.setVisible(true);
			}
		});
		btnNewButton.setBounds(142, 32, 136, 23);
		contentPane.add(btnNewButton);

	}

	@Override
	public void mouseClicked(MouseEvent e) {

	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited(MouseEvent e) {

	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == mntmOpen) {
			clickOnOpen();
		} else if (e.getSource() == mntmSave) {
			clickOnSave();
		} else if (e.getSource() == addPointButton) {
			clickOnAddPointButton();
		} else if (e.getSource().equals(btnNewButton_1)) {
			clickOnDeletePointButton();

		} else if (e.getSource().equals(mntmDeleteLinguisticVariable)) {
			AddLinguisticVariableDialog lgV = new AddLinguisticVariableDialog(
					variables, Boolean.FALSE);
			lgV.setVisible(true);

		} else if (e.getSource().equals(mntmAddLinguisticVarable)) {
			AddLinguisticVariableDialog lgV = new AddLinguisticVariableDialog(
					variables);
			lgV.setVisible(true);

			comboBox.removeAllItems();
			MutableComboBoxModel model = (MutableComboBoxModel) comboBox
					.getModel();

			for (LinguisticVariable lgv : variables) {

				model.addElement(lgv.getName());
			}

			redrawGraph();

		} else if (e.getSource().equals(mntmDeleteLinguisticValue)) {
			AddValueDialog lgV = new AddValueDialog(variables, false);
			lgV.setVisible(true);
			redrawGraph();

		} else if (e.getSource().equals(mntmAddLinguisticValue)) {
			AddValueDialog lgV = new AddValueDialog(variables);
			lgV.setVisible(true);
			redrawGraph();

		}

	}

	private void clickOnSave() {
		for (LinguisticVariable var : variables) {
			for (LinguisticValue value : var.getLinguisticValues()) {
				value.save();
			}
		}
		if(target == null ){
			JFileChooser fileChooser = new JFileChooser();
	          fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
	      // Demonstrate "Open" dialog:
	      int returnValue = fileChooser.showSaveDialog(this);
	      if (returnValue == JFileChooser.APPROVE_OPTION) {
	      //
	          String fileName="\\data.xml";
	          
	          String directorySelected = fileChooser.getCurrentDirectory().toString()+fileName;
	          target = new File(directorySelected);
	      }
	         
			doc = createDocument();
			XMLWriter output;
			try {
				output = new XMLWriter(new FileWriter(target));
				output.write(doc);
				output.close();

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		else{
		XMLWriter output;
		try {
			output = new XMLWriter(new FileWriter(target));
			output.write(doc);
			output.close();

		} catch (IOException e) {
			
			e.printStackTrace();
		}
		}
	}
	 public Document createDocument() {
	        Document document = DocumentHelper.createDocument();
	        Element root = document.addElement( "root" );

	        
	      for(int indexvariable=0; indexvariable< variables.size(); indexvariable++){
	    	  Element tag = root.addElement( "variable" );
	    	  System.out.println("Variable Tag");
	    	  tag.addAttribute("name", variables.get(indexvariable).getName());
	    	  for(int indexvalue=0; indexvalue<variables.get(indexvariable).getLinguisticValues().size(); indexvalue++){
	    		  Element subtag = tag.addElement("value");
	    		  subtag.addAttribute("name", variables.get(indexvariable).getValueNames().get(indexvalue));
	    		  for(int indexpoints=0; indexpoints< variables.get(indexvariable).getLinguisticValues().size(); indexpoints++){
	    			  Element subsubtag = subtag.addElement("point");
	    			 for(int points=0; points<variables.get(indexvariable).getLinguisticValues().get(indexpoints).getPoints().size(); points++){
	    				 
	    				 subsubtag.addAttribute("x", variables.get(indexvariable).getLinguisticValues().get(indexpoints).getPoints().get(points).first+"");
	    				 subsubtag.addAttribute("y", variables.get(indexvariable).getLinguisticValues().get(indexpoints).getPoints().get(points).second+"");
	    			 }
	    			  
	    			  System.out.println("Points Tag");
	    		  }
	    	  }
	    	  
	      }
	        return document;
	    }
	private void clickOnAddPointButton() {
		AddPointDialog dlg = new AddPointDialog();
		dlg.setModal(true);
		dlg.setSelection(variables.get(selectedVariableIndex).getValueNames());
		dlg.setVisible(true);
		HashMap<String, ArrayList<Pair<Double, Double>>> hashmap = dlg
				.getPoints();
		LinguisticVariable var = variables.get(selectedVariableIndex);
		for (LinguisticValue value : var.getLinguisticValues()) {
			if (hashmap.containsKey(value.getName())) {
				value.addPoints(hashmap.get(value.getName()));
			}
		}
		repaint();revalidate();
	}

	private void clickOnDeletePointButton() {
		AddPointDialog dlg = new AddPointDialog(false, variables);
		dlg.setModal(true);
		dlg.setVisible(true);
		repaint();revalidate();
	}

	private void redrawGraph() {
		((GraphPanel) graph).redraw(selectedVariableIndex);
	}

	private void clickOnOpen() {
		JFileChooser fileChooser = new JFileChooser();
		int result = fileChooser.showOpenDialog(contentPane);
		/*
		 * JFileChooser.CANCEL_OPTION JFileChooser.APPROVE_OPTION
		 * JFileChooser.ERROR_OPTION if an error occurs or the dialog is
		 * dismissed
		 */
		switch (result) {
		case JFileChooser.CANCEL_OPTION:
			break;
		case JFileChooser.APPROVE_OPTION:
			File selected = fileChooser.getSelectedFile();
			getData(selected);
			redrawGraph();
			break;
		case JFileChooser.ERROR_OPTION:
			break;
		}
	}

	private void getData(File file) {
		try {
			this.target = file;
			String xml = readFile(file);
			doc = DocumentHelper.parseText(xml);
			rootElt = doc.getRootElement();
			List<Element> list = rootElt.elements("variable");

			for (Element e : list) {
				variables.add(new LinguisticVariable(e));
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		for (LinguisticVariable variable : variables) {
			comboBox.addItem(variable.getName());
		}
	}

	private String readFile(File path) throws Exception {
		BufferedReader br = new BufferedReader(new FileReader(path));
		StringBuilder sb = new StringBuilder();
		try {
			String line = br.readLine();

			while (line != null) {
				sb.append(line);
				sb.append(System.lineSeparator());
				line = br.readLine();
			}

		} finally {
			br.close();
		}
		return sb.toString();
	}

	@Override
	public void itemStateChanged(ItemEvent arg0) {
		this.selectedVariableIndex = comboBox.getSelectedIndex();
		redrawGraph();

	}
}
